异步操作
Node 采用 Chrome V8 引擎处理 javascript 脚本,V8最大的特点就是单线程运行,一次只能运行一个任务。
Node 大量采用异步操作,即任务不是马上执行,而是插在任务队列的尾部,等到前面的任务执行完毕后再执行,即:利用回调处理操作。
Node 采用错误优先的回掉规则,即:回调函数一定作为参数的最后一个参数出现,回调函数的第一个参数默认接收错误信息,第二个参数才是真正的回掉数据,这样便于外界获取调用的错误情况。
原因是:大部分操作都是异步的方式,无法通过 try catch 捕获异常, so 采用错误优先的回调函数,第一个参数为上一步的错误信息。
非阻塞异步事件机制
我们看一下 node 中的事件驱动和非阻塞机制:
举个栗子是这样子的,读文件的过程:
对于异步的调用和执行,node 会将任务和任务的回掉函数放入 event loop 中依次执行,这里就是读取文件的操作和回调。
上图可以说明,node 通过主线程之外的 I/O 线程来执行 evnet loop 中的任务队列,而且,在I/O操作时不会阻止其他请求,同时无需承担每个请求所产生的线程/进程的成本。
Event loop 是指处理外部事件,并把外部事件转换为回调来进行调用的实体。所以,I/O调用的同时,server 就可以去处理另一个请求。在一次I/O调用中,你的代码保存回调函数并把控制权交回到 node.js(主线程)运行时。当数据加载完毕可以访问时,就可以执行回调函数了。
我们都知道,node是单线程的,前面说到node的事件机制是基于 event loop 的,下面通过几张图更加说明了node的事件机制:
node本身是单线程的,但是 node 内部是多线程的,对于为什么我们说它的单线程的,是因为对于node 外部调用和操作的所有API 都是通过主线程这单个线程来操作的,而阻塞的各种文件操作和网络操作,是派发给内node 内部的线程去做的,比如前面所说的 I/O 线程。
简单来说就三点:
- node 平台将一个任务连同该任务的回调函数放到一个事件循环系统中;
- 事件循环高效的管理node 系统内部线程池,同时高效执行每一个任务;
- 当任务执行完成过后自动执行回调函数。
这就是 node 的非阻塞事件机制,它的优势有:
- 提高代码响应效率
- 充分利用单核 CPU 的优势
- 改善 I/O 的不可预测带来的问题
完~